import { type GraphicObject, GraphicType } from './GraphicObject';
import HistoryManager from './HistoryManager';
import LayerManager from './LayerManager';
import SelectionManager from './SelectionManager';
import { Circle, Line, Polygon, Rectangle } from './shapes';
import TransformHandle, { TransformHandleType } from './TransformHandle';
import TransformManager from './TransformManager';
import type {
  InteractionMode,
  Point,
  WorldData,
  WorldEvent,
  WorldEventMap,
} from './types';
import ViewController from './ViewController';

export interface WorldOptions {
  gridSize?: number;
  gridVisible?: boolean;
  snapToGrid?: boolean;
  backgroundColor?: string;
}

export class World {
  // 核心属性
  private canvas: HTMLCanvasElement;
  private ctx: CanvasRenderingContext2D;
  private options: WorldOptions;

  // 组件
  private viewController: ViewController;
  private selectionManager: SelectionManager;
  private layerManager: LayerManager;
  private historyManager: HistoryManager;

  // 数据
  private objects: GraphicObject[] = [];
  private objectMap: Map<string, GraphicObject> = new Map();
  private transformHandles: TransformHandle[] = [];

  // 交互状态
  private interactionMode: InteractionMode = 'select';
  private isDragging: boolean = false;
  private dragStartPoint: Point = { x: 0, y: 0 };
  private activeTransformHandle: TransformHandle | null = null;
  private lastMousePoint: Point = { x: 0, y: 0 };

  // 事件监听
  private listeners: Map<WorldEvent, Function[]> = new Map();

  // 渲染状态
  private animationFrameId: number | null = null;
  private needsRender: boolean = true;

  constructor(canvas: HTMLCanvasElement, options: WorldOptions = {}) {
    this.canvas = canvas;
    this.ctx = canvas.getContext('2d')!;
    this.options = {
      gridSize: 20,
      gridVisible: true,
      snapToGrid: false,
      backgroundColor: '#f8f9fa',
      ...options,
    };

    // 初始化组件
    this.viewController = new ViewController(canvas);
    this.selectionManager = new SelectionManager();
    this.layerManager = new LayerManager();
    this.historyManager = new HistoryManager();

    // 设置事件监听
    this.setupEventListeners();

    // 开始渲染循环
    this.startRenderLoop();
  }

  /**
   * 初始化World
   */
  initialize(): void {
    // 创建默认图层
    this.createLayer('default', '默认图层');

    // 触发初始化事件
    this.emit('initialized', {});
  }

  /**
   * 销毁World
   */
  destroy(): void {
    // 停止渲染循环
    this.stopRenderLoop();

    // 移除事件监听
    this.removeEventListeners();

    // 清理数据
    this.objects = [];
    this.objectMap.clear();
    this.transformHandles = [];
    this.selectionManager.destroy();
    this.layerManager.destroy();

    // 触发销毁事件
    this.emit('destroyed', {});
  }

  /**
   * 添加图形对象
   */
  addObject(object: GraphicObject, layerId: string = 'default'): void {
    this.objects.push(object);
    this.objectMap.set(object.id, object);

    // 添加到图层
    this.layerManager.addObjectToLayer(object, layerId);

    // 记录历史
    this.historyManager.recordObjectCreated(object);

    // 触发事件
    this.emit('objectAdded', { object });
    this.requestRender();
  }

  /**
   * 移除图形对象
   */
  removeObject(object: GraphicObject): void {
    const index = this.objects.indexOf(object);
    if (index > -1) {
      this.objects.splice(index, 1);
      this.objectMap.delete(object.id);

      // 从图层中移除
      this.layerManager.removeObjectFromLayer(object);

      // 从选择中移除
      this.selectionManager.deselect(object);

      // 记录历史
      this.historyManager.recordObjectDeleted(object);

      // 触发事件
      this.emit('objectRemoved', { object });
      this.requestRender();
    }
  }

  /**
   * 创建图层
   */
  createLayer(id: string, name: string): void {
    this.layerManager.createLayer(id, name);
  }

  /**
   * 选择对象
   */
  select(object: GraphicObject, additive: boolean = false): void {
    this.selectionManager.select(object, additive);
    this.updateTransformHandles();
    this.requestRender();
  }

  /**
   * 取消选择对象
   */
  deselect(object: GraphicObject): void {
    this.selectionManager.deselect(object);
    this.updateTransformHandles();
    this.requestRender();
  }

  /**
   * 清空选择
   */
  clearSelection(): void {
    this.selectionManager.clearSelection();
    this.transformHandles = [];
    this.requestRender();
  }

  /**
   * 移动选中的对象
   */
  translateSelected(delta: Point): void {
    const selected = this.selectionManager.getSelectedObjects();

    // 记录变换前的状态
    const oldStates = selected.map((obj) => ({
      id: obj.id,
      transform: { ...obj.transform },
      style: { ...obj.style },
      layerId: obj.layerId,
    }));

    for (const obj of selected) {
      obj.translate(delta);
      this.emit('transformChanged', { object: obj });
    }

    // 记录历史
    this.historyManager.recordMultipleObjects(
      'multiple_objects_moved',
      selected,
      oldStates,
    );

    this.updateTransformHandles();
    this.requestRender();
  }

  /**
   * 旋转选中的对象
   */
  rotateSelected(angle: number, center?: Point): void {
    const selected = this.selectionManager.getSelectedObjects();
    const rotationCenter = center || this.selectionManager.getSelectionCenter();

    if (rotationCenter) {
      // 记录变换前的状态
      const oldStates = selected.map((obj) => ({
        id: obj.id,
        transform: { ...obj.transform },
        style: { ...obj.style },
        layerId: obj.layerId,
      }));

      for (const obj of selected) {
        obj.rotate(angle, rotationCenter);
        this.emit('transformChanged', { object: obj });
      }

      // 记录历史
      this.historyManager.recordMultipleObjects(
        'multiple_objects_rotated',
        selected,
        oldStates,
      );

      this.updateTransformHandles();
      this.requestRender();
    }
  }

  /**
   * 缩放选中的对象
   */
  scaleSelected(scaleX: number, scaleY: number, center?: Point | null): void {
    const selected = this.selectionManager.getSelectedObjects();
    const scaleCenter = center || this.selectionManager.getSelectionCenter();

    if (scaleCenter) {
      // 记录变换前的状态
      const oldStates = selected.map((obj) => ({
        id: obj.id,
        transform: { ...obj.transform },
        style: { ...obj.style },
        layerId: obj.layerId,
      }));

      for (const obj of selected) {
        obj.scale(scaleX, scaleY, scaleCenter);
        this.emit('transformChanged', { object: obj });
      }

      // 记录历史
      this.historyManager.recordMultipleObjects(
        'multiple_objects_scaled',
        selected,
        oldStates,
      );

      this.updateTransformHandles();
      this.requestRender();
    }
  }

  /**
   * 设置交互模式
   */
  setInteractionMode(mode: InteractionMode): void {
    this.interactionMode = mode;
    this.updateCursor();
  }

  /**
   * 获取视图变换
   */
  getViewTransform() {
    return this.viewController.getViewTransform();
  }

  /**
   * 适应视图到所有对象
   */
  fitToView(): void {
    this.viewController.fitToView(this.objects);
    this.requestRender();
  }

  /**
   * 重置视图
   */
  resetView(): void {
    this.viewController.resetView();
    this.requestRender();
  }

  /**
   * 图层管理方法
   */

  /**
   * 获取所有图层
   */
  getAllLayers() {
    return this.layerManager.getAllLayers();
  }

  /**
   * 获取活动图层
   */
  getActiveLayer() {
    return this.layerManager.getActiveLayer();
  }

  /**
   * 设置活动图层
   */
  setActiveLayer(id: string): boolean {
    return this.layerManager.setActiveLayer(id);
  }

  /**
   * 重命名图层
   */
  renameLayer(id: string, newName: string): boolean {
    return this.layerManager.renameLayer(id, newName);
  }

  /**
   * 设置图层可见性
   */
  setLayerVisibility(id: string, visible: boolean): boolean {
    return this.layerManager.setLayerVisibility(id, visible);
  }

  /**
   * 设置图层锁定状态
   */
  setLayerLocked(id: string, locked: boolean): boolean {
    return this.layerManager.setLayerLocked(id, locked);
  }

  /**
   * 移动图层顺序
   */
  moveLayer(id: string, newIndex: number): boolean {
    return this.layerManager.moveLayer(id, newIndex);
  }

  /**
   * 撤销重做方法
   */

  /**
   * 撤销操作
   */
  undo(): boolean {
    const result = this.historyManager.undo(this.objectMap);
    if (result) {
      this.requestRender();
    }
    return result;
  }

  /**
   * 重做操作
   */
  redo(): boolean {
    const result = this.historyManager.redo(this.objectMap);
    if (result) {
      this.requestRender();
    }
    return result;
  }

  /**
   * 是否可以撤销
   */
  canUndo(): boolean {
    return this.historyManager.canUndo();
  }

  /**
   * 是否可以重做
   */
  canRedo(): boolean {
    return this.historyManager.canRedo();
  }

  /**
   * 获取所有图形对象
   */
  getObjects(): GraphicObject[] {
    return [...this.objects];
  }

  /**
   * 获取选中的图形对象
   */
  getSelectedObjects(): GraphicObject[] {
    return this.selectionManager.getSelectedObjects();
  }

  /**
   * 清空历史记录
   */
  clearHistory(): void {
    this.historyManager.clear();
  }

  /**
   * 坐标转换方法
   */

  /**
   * 世界坐标转换为对象局部坐标
   */
  worldToLocal(worldPoint: Point, transform: any): Point {
    return TransformManager.worldToLocal(worldPoint, transform);
  }

  /**
   * 对象局部坐标转换为世界坐标
   */
  localToWorld(localPoint: Point, transform: any): Point {
    return TransformManager.localToWorld(localPoint, transform);
  }

  /**
   * 事件监听方法
   */
  on<K extends WorldEvent>(
    event: K,
    callback: (data: WorldEventMap[K]) => void,
  ): void {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, []);
    }
    this.listeners.get(event)!.push(callback);
  }

  /**
   * 序列化World数据
   */
  serialize(): WorldData {
    return {
      version: '1.0.0',
      objects: this.objects.map((obj) => obj.serialize()),
      layers: this.layerManager.serialize(),
      viewTransform: this.viewController.getViewTransform(),
      history: this.historyManager.serialize(),
    };
  }

  /**
   * 从数据反序列化World
   */
  deserialize(data: WorldData): void {
    // 清空当前数据
    this.objects = [];
    this.objectMap.clear();
    this.selectionManager.clearSelection();
    this.layerManager.destroy();
    this.historyManager.clear();

    // 创建对象映射
    const objectMap = new Map<string, GraphicObject>();

    // 创建对象
    for (const objData of data.objects) {
      const obj = this.createObjectFromData(objData);
      if (obj) {
        this.objects.push(obj);
        objectMap.set(obj.id, obj);
      }
    }

    // 反序列化图层
    if (data.layers) {
      this.layerManager.deserialize(data.layers, objectMap);
    }

    // 反序列化历史记录
    if (data.history) {
      this.historyManager.deserialize(data.history);
    }

    // 设置视图变换
    this.viewController.setViewTransform(data.viewTransform);

    // 更新对象映射
    this.objectMap = objectMap;

    this.requestRender();
  }

  /**
   * 私有方法
   */

  private setupEventListeners(): void {
    this.canvas.addEventListener('mousedown', this.handleMouseDown.bind(this));
    this.canvas.addEventListener('mousemove', this.handleMouseMove.bind(this));
    this.canvas.addEventListener('mouseup', this.handleMouseUp.bind(this));
    this.canvas.addEventListener('wheel', this.handleWheel.bind(this));
    this.canvas.addEventListener(
      'contextmenu',
      this.handleContextMenu.bind(this),
    );

    // 键盘事件
    document.addEventListener('keydown', this.handleKeyDown.bind(this));
    document.addEventListener('keyup', this.handleKeyUp.bind(this));
  }

  private removeEventListeners(): void {
    // 移除canvas事件监听
    this.canvas.removeEventListener(
      'mousedown',
      this.handleMouseDown.bind(this),
    );
    this.canvas.removeEventListener(
      'mousemove',
      this.handleMouseMove.bind(this),
    );
    this.canvas.removeEventListener('mouseup', this.handleMouseUp.bind(this));
    this.canvas.removeEventListener('wheel', this.handleWheel.bind(this));
    this.canvas.removeEventListener(
      'contextmenu',
      this.handleContextMenu.bind(this),
    );

    // 移除键盘事件监听
    document.removeEventListener('keydown', this.handleKeyDown.bind(this));
    document.removeEventListener('keyup', this.handleKeyUp.bind(this));
  }

  private handleMouseDown(event: MouseEvent): void {
    event.preventDefault();

    const worldPoint = this.viewController.screenToWorld({
      x: event.offsetX,
      y: event.offsetY,
    });

    this.dragStartPoint = worldPoint;
    this.lastMousePoint = worldPoint;

    // 检查是否点击了变换控制柄
    this.activeTransformHandle = this.getTransformHandleAtPoint(worldPoint);

    if (this.activeTransformHandle) {
      this.isDragging = true;
      return;
    }

    // 检查是否点击了对象
    const clickedObject = this.selectionManager.selectAtPoint(
      worldPoint,
      this.objects,
    );

    if (clickedObject) {
      if (event.ctrlKey || event.metaKey) {
        // Ctrl+点击：多选/取消选择
        if (this.selectionManager.isSelected(clickedObject)) {
          this.deselect(clickedObject);
        } else {
          this.select(clickedObject, true);
        }
      } else {
        // 普通点击：选择对象
        this.select(clickedObject);
      }
      this.isDragging = true;
    } else {
      // 点击空白区域：清空选择
      if (!event.ctrlKey && !event.metaKey) {
        this.clearSelection();
      }

      // 开始框选或视图操作
      this.isDragging = true;
    }
  }

  private handleMouseMove(event: MouseEvent): void {
    const worldPoint = this.viewController.screenToWorld({
      x: event.offsetX,
      y: event.offsetY,
    });

    if (this.isDragging) {
      const delta = {
        x: worldPoint.x - this.lastMousePoint.x,
        y: worldPoint.y - this.lastMousePoint.y,
      };

      if (this.activeTransformHandle) {
        // 变换控制柄拖动
        this.handleTransformHandleDrag(delta);
      } else if (this.selectionManager.getSelectedObjects().length > 0) {
        // 对象拖动
        this.translateSelected(delta);
      } else {
        // 视图拖动
        this.viewController.pan({
          x: event.movementX,
          y: event.movementY,
        });
      }
    }

    this.lastMousePoint = worldPoint;
    this.updateCursor();
  }

  private handleMouseUp(event: MouseEvent): void {
    this.isDragging = false;
    this.activeTransformHandle = null;
  }

  private handleWheel(event: WheelEvent): void {
    event.preventDefault();

    const delta = event.deltaY > 0 ? 0.9 : 1.1;
    const point = { x: event.offsetX, y: event.offsetY };

    this.viewController.zoom(delta, point);
    this.requestRender();
  }

  private handleContextMenu(event: MouseEvent): void {
    event.preventDefault();
  }

  private handleKeyDown(event: KeyboardEvent): void {
    switch (event.key.toLowerCase()) {
      case 'g': // 移动模式
        if (this.selectionManager.getSelectedObjects().length > 0) {
          this.setInteractionMode('move');
        }
        break;
      case 'r': // 旋转模式
        if (this.selectionManager.getSelectedObjects().length > 0) {
          this.setInteractionMode('rotate');
        }
        break;
      case 's': // 缩放模式
        if (this.selectionManager.getSelectedObjects().length > 0) {
          this.setInteractionMode('scale');
        }
        break;
      case 'a': // 全选/取消全选
        if (event.ctrlKey || event.metaKey) {
          event.preventDefault();
          if (this.objects.length > 0) {
            this.selectionManager.selectAll(this.objects);
            this.updateTransformHandles();
            this.requestRender();
          }
        }
        break;
      case 'delete': {
        // 删除选中对象
        const selected = this.selectionManager.getSelectedObjects();
        for (const obj of selected) {
          this.removeObject(obj);
        }
        break;
      }
      case ' ': // 空格键：临时切换到视图平移模式
        this.setInteractionMode('pan');
        break;
    }
  }

  private handleKeyUp(event: KeyboardEvent): void {
    if (event.key === ' ') {
      // 空格键释放：恢复之前的模式
      this.setInteractionMode('select');
    }
  }

  private handleTransformHandleDrag(delta: Point): void {
    if (!this.activeTransformHandle) return;

    const selected = this.selectionManager.getSelectedObjects();
    if (selected.length === 0) return;

    switch (this.activeTransformHandle.type) {
      case TransformHandleType.MOVE:
        this.translateSelected(delta);
        break;
      case TransformHandleType.ROTATE: {
        const center = this.selectionManager.getSelectionCenter();
        if (center) {
          const angle = delta.x * 0.01; // 转换为角度
          this.rotateSelected(angle, center);
        }
        break;
      }
      case TransformHandleType.SCALE_X:
        this.scaleSelected(
          1 + delta.x * 0.01,
          1,
          this.selectionManager.getSelectionCenter(),
        );
        break;
      case TransformHandleType.SCALE_Y:
        this.scaleSelected(
          1,
          1 + delta.y * 0.01,
          this.selectionManager.getSelectionCenter(),
        );
        break;
      case TransformHandleType.SCALE_XY: {
        const scale = 1 + (delta.x + delta.y) * 0.005;
        this.scaleSelected(
          scale,
          scale,
          this.selectionManager.getSelectionCenter(),
        );
        break;
      }
    }
  }

  private updateTransformHandles(): void {
    this.transformHandles = [];

    const selected = this.selectionManager.getSelectedObjects();
    if (selected.length === 0) return;

    const bounds = this.selectionManager.getSelectionBounds();
    if (!bounds) return;

    // 添加移动控制柄（中心）
    const center = this.selectionManager.getSelectionCenter();
    if (center) {
      this.transformHandles.push(
        new TransformHandle(TransformHandleType.MOVE, center),
      );
    }

    // 添加旋转控制柄（上方）
    this.transformHandles.push(
      new TransformHandle(TransformHandleType.ROTATE, {
        x: bounds.x + bounds.width / 2,
        y: bounds.y - 30,
      }),
    );

    // 添加缩放控制柄
    this.transformHandles.push(
      new TransformHandle(TransformHandleType.SCALE_X, {
        x: bounds.x + bounds.width,
        y: bounds.y + bounds.height / 2,
      }),
    );
    this.transformHandles.push(
      new TransformHandle(TransformHandleType.SCALE_Y, {
        x: bounds.x + bounds.width / 2,
        y: bounds.y + bounds.height,
      }),
    );
    this.transformHandles.push(
      new TransformHandle(TransformHandleType.SCALE_XY, {
        x: bounds.x + bounds.width,
        y: bounds.y + bounds.height,
      }),
    );
  }

  private getTransformHandleAtPoint(point: Point): TransformHandle | null {
    for (const handle of this.transformHandles) {
      if (handle.contains(point, this.viewController.getViewTransform())) {
        return handle;
      }
    }
    return null;
  }

  private updateCursor(): void {
    if (this.activeTransformHandle) {
      this.canvas.style.cursor = this.activeTransformHandle.getCursor();
    } else if (this.isDragging) {
      this.canvas.style.cursor = 'grabbing';
    } else if (this.interactionMode === 'pan') {
      this.canvas.style.cursor = 'grab';
    } else {
      this.canvas.style.cursor = 'default';
    }
  }

  private createObjectFromData(data: any): GraphicObject | null {
    switch (data.type) {
      case GraphicType.RECTANGLE:
        return new Rectangle(
          data.width,
          data.height,
          data.transform,
          data.style,
          data.layerId,
          data.cornerRadius,
        );
      case GraphicType.CIRCLE:
        return new Circle(
          data.radius,
          data.transform,
          data.style,
          data.layerId,
        );
      case GraphicType.POLYGON:
        return new Polygon(
          data.points,
          data.transform,
          data.style,
          data.layerId,
          data.closed,
        );
      case GraphicType.LINE:
        return new Line(
          data.start,
          data.end,
          data.transform,
          data.style,
          data.layerId,
        );
      default:
        return null;
    }
  }

  private startRenderLoop(): void {
    const render = () => {
      if (this.needsRender) {
        this.render();
        this.needsRender = false;
      }
      this.animationFrameId = requestAnimationFrame(render);
    };
    render();
  }

  private stopRenderLoop(): void {
    if (this.animationFrameId) {
      cancelAnimationFrame(this.animationFrameId);
      this.animationFrameId = null;
    }
  }

  private requestRender(): void {
    this.needsRender = true;
  }

  private render(): void {
    // 清空画布
    this.ctx.fillStyle = this.options.backgroundColor!;
    this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);

    // 绘制网格
    if (this.options.gridVisible) {
      this.renderGrid();
    }

    // 应用视图变换
    this.ctx.save();
    const viewTransform = this.viewController.getViewTransform();
    TransformManager.applyTransform(this.ctx, {
      position: viewTransform.offset,
      rotation: viewTransform.rotation,
      scale: { x: viewTransform.scale, y: viewTransform.scale },
      anchor: { x: 0, y: 0 },
    });

    // 绘制对象
    for (const obj of this.objects) {
      obj.draw(this.ctx, viewTransform);
    }

    // 绘制选择框
    this.renderSelection();

    // 绘制变换控制柄
    this.renderTransformHandles();

    this.ctx.restore();
  }

  private renderGrid(): void {
    const gridSize = this.options.gridSize!;
    const viewTransform = this.viewController.getViewTransform();
    const scaledGridSize = gridSize * viewTransform.scale;

    if (scaledGridSize < 2) return; // 网格太小就不显示

    this.ctx.save();
    this.ctx.strokeStyle = '#e0e0e0';
    this.ctx.lineWidth = 1;

    const startX =
      Math.floor(-viewTransform.offset.x / scaledGridSize) * scaledGridSize;
    const startY =
      Math.floor(-viewTransform.offset.y / scaledGridSize) * scaledGridSize;
    const endX = this.canvas.width / viewTransform.scale;
    const endY = this.canvas.height / viewTransform.scale;

    for (let x = startX; x < endX; x += scaledGridSize) {
      this.ctx.beginPath();
      this.ctx.moveTo(x, startY);
      this.ctx.lineTo(x, endY);
      this.ctx.stroke();
    }

    for (let y = startY; y < endY; y += scaledGridSize) {
      this.ctx.beginPath();
      this.ctx.moveTo(startX, y);
      this.ctx.lineTo(endX, y);
      this.ctx.stroke();
    }

    this.ctx.restore();
  }

  private renderSelection(): void {
    const selected = this.selectionManager.getSelectedObjects();
    if (selected.length === 0) return;

    this.ctx.save();
    this.ctx.strokeStyle = '#3498db';
    this.ctx.lineWidth = 2;
    this.ctx.setLineDash([5, 5]);

    for (const obj of selected) {
      const bbox = obj.getBoundingBox();
      this.ctx.strokeRect(bbox.x, bbox.y, bbox.width, bbox.height);
    }

    this.ctx.restore();
  }

  private renderTransformHandles(): void {
    for (const handle of this.transformHandles) {
      handle.draw(this.ctx, this.viewController.getViewTransform());
    }
  }

  private emit<K extends WorldEvent>(event: K, data: WorldEventMap[K]): void {
    const callbacks = this.listeners.get(event);
    if (callbacks) {
      for (const callback of callbacks) {
        callback(data);
      }
    }
  }
}

export default World;
